`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/07/24 11:56:42
// Design Name: 
// Module Name: register_pc
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module register_pc(
    clk,reset_n,addr,addr_ir,op_j_exe,op_b_mem,offset_j,offset_b_mem,addr_next,zero_mem,nop_j_out,nop_b_out,lu,nop,addr_next_id,
    addr_next_exe
    );

    input clk,reset_n,nop;
    input [31:0] addr,addr_next_id,addr_next_exe;
    input op_j_exe,op_b_mem;
    input [31:0] offset_j,offset_b_mem;
    input zero_mem;
    input lu;
    output reg [31:0] addr_ir,addr_next;
    output reg nop_j_out,nop_b_out;

    wire [31:0] ad;

    assign ad = addr +  32'b100;

    always @(posedge clk,negedge reset_n) begin
        if(~reset_n)
            addr_ir <= 32'b0;
        else begin
            addr_ir <= ad;
            casez({lu,op_j_exe,op_b_mem,zero_mem})
                4'b1??? : begin
                    addr_ir <= ad + {{29{1'b1}},3'b000};
                end
                4'b01?? : begin
                    addr_ir <= addr_next_id + offset_j;
                end
                4'b0000 : begin
                    addr_ir <= addr_next_exe + offset_b_mem;
                end
            endcase
        end
    end

    always @(*) begin
        nop_b_out = 1'b0;
        nop_j_out = 1'b0;
        casez({op_j_exe,op_b_mem,zero_mem})
            3'b1?? : begin
                nop_j_out = 1'b1;
            end
            3'b000 : begin
                nop_b_out = 1'b1;
            end
        endcase
    end

    always @(posedge clk) begin
        if(nop)
            addr_next <= 32'bx;
        else
            addr_next <= ad;
    end

endmodule
